A/D変換の動作確認(3)
多入力のA/D変換法について
A/D変換器のポートを選ぶ
A/D変換器の入力ポートですが、PIC16F877は、(RA0/AN0),(RA1/AN1), (RA2/AN2),(RA3/AN3),(RA5/AN4),(RE0/AN5)
, (RE1/AN6) , (RE2/AN7) の全8ポートあります。ここでは、例として(RA0/AN0)
,(RA2/AN2),(RA3/AN3)を使う設定とします。「A/D変換の制御法」の表3.A/D ポートの設定表にて、A/Dポートの設定を確認します。PCFGx=「0000」のとき、全RA,および全REポートがA/D変換入力ポートとなります。また、PCFGx=「0010」のとき、全RAポートがA/D変換入力ポートとなり、REポートはディジタル入出力ポートになることが分かります。その他に、PCFGx=「1001」のとき、全RAポートとRE0ポートがA/D変換入力ポートとなり、RE1,RE2ポートはディジタル入出力ポートになることが分かります。ここでは、REポートまでA/D変換ポートにする必要性はありませんので、PCFGx=「0010」を選択します。
ここで、 「A/D変換の制御法」の表1.ADCON0レジスタの機能説明表にて、アナログチャネル指定ビットを、
CHSx=「000」とすることで、CH0(RA0)の指定になります。
CHSx=「010」とすることで、CH2(RA2)の指定になります。
CHSx=「011」とすることで、CH3(RA3)の指定になります。
A/D結果レジスタの右/左詰めについて
これまでの例と同様に、結果を右詰めにします。したがって、
ADRESH<1:0>→PortB<1:0>
ADRESL<7:0>→PortD<7:0>
という配置に出力させます。
すなわち、10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>とします。
A/D変換のクロックの選択
「A/D変換の制御法」の表4.A/D変換用クロックの選択を参照してください。20MHzのシステムクロックでは、Fosc/32を選択することになります。よって、ADCS1=「1」,ADCS0=「0」と決まります。
ADCON0レジスタの決定
(「A/D変換の制御法」の図1. ADCON0レジスタの構成を参照してください)
CH0(RA0)の場合(初期設定時)
ということで、ADCON0→B’10000000’ (80H)
CH2(RA2)の場合(初期設定時)
ということで、ADCON0→B’10010000’ (90H)
CH3(RA3)の場合(初期設定時)
ということで、ADCON0→B’10011000’ (98H)
ADCON1レジスタの決定
(「A/D変換の制御法」の図2. ADCON1レジスタの構成を参照してください)
ADCON1レジスタの内容の決定
ということで、ADCON1→B’10000010’ (82H)
ハード側の接続について
A/D変換の結果を簡単に確認するためLEDを接続し点灯させます。LEDの接続ポートですが、先ほどの例のように私のターゲットボードでは、PortBとPortDが隣り合って並んでいますので、図1のように10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>と接続します。
また、A/D変換入力ポートは3つありますので、RCポートのLEDを点灯させることで、どのポートでA/D変換が行われているかを確認できるようにしました。すなわち、CH0のときがRC0、CH2のときがRC2、CH3のときがRC3ポートのLEDを点灯するようにします。
A/D変換入力の3端子ですが、簡単のためそれぞれ10kΩの可変抵抗を接続し、0〜5Vの可変電圧を入力できるようにしました。アナログソースの最大推奨インピーダンスは
10kΩですから、それより大きい抵抗値は好ましくありません。
![]() |
図1.多入力A/D変換の動作確認回路 |
アナログ入力端子ですが、テスタなどを接続してアナログの電圧値が分かるようにします。また、アナログ入力電圧が安定しない場合には、10kΩの可変抵抗に
0.1μF程度のセラミックコンデンサを接続するとよいでしょう。
多入力A/D変換動作の確認プログラム
図2に複数入力のA/D変換動作のフローチャートを示します。
プログラムの解説については、「プログラムの説明(3)」の項をご参照ください。
図2.A/D変換プログラム(3)
フローチャート
(注)以下に示すプログラムには、ホームページ画面作成の都合上、空白として全角文字のスペースなどが挿入されています。したがって、下記プログラムリストをそのままコピーしてMPLABのソースファイルとされた場合には、エラーとなることがあります。
→ここをクリックして、下記のプログラムをダウンロードするようにしてください。
ファイル名:「adconv3.asm」 サイズ5.40kバイト
→ここをクリックして、下記のオブジェクトファイルをダウンロードするようにしてください。
ファイル名:「adconv3.hex」 サイズ484バイト
;*********************************************************** ; A/D変換動作チェックプログラム(3) ; A/D変換入力 3端子(CH0/RA0),(CH2/RA2),(CH3/RA3) ; A/D変換の結果は LED 点灯により確認 ; RB1(MSB),RB0,RD7,RD6,RD5,RD4,RD3,RD2,RD1,RD0(LSB) ; の10ビット ; 3入力の CH 判別は LED 点灯により確認 ; CH0 → RC0 を点灯 ; CH2 → RC2 を点灯 ; CH3 → RC3 を点灯 ; A/D 割り込みは使用せず、簡単のため GO ビットで判断 ;*********************************************************** |
|
LIST P=PIC16F877 INCLUDE P16F877.INC |
;(1)プロセッサの種別指定 ;(2)インクルードファイルの指定 |
;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** |
|
COUNT EQU 20H COUNT1 EQU 21H COUNT2 EQU 22H COUNT3 EQU 23H COUNT4 EQU 24H PC_LOC EQU 25H ORG 0 |
;(3)ループカウンタ ; ループカウンタ1 ; ループカウンタ2 ; ループカウンタ3 ; ループカウンタ4 ; ロケーションカウンタ ;(4)プログラムの開始番地の指定 |
;*********************************************************** ; 入出力ピン初期化 ;*********************************************************** |
|
BSF STATUS,RP0 MOVLW B'10000010' MOVWF ADCON1 CLRF TRISB CLRF TRISC CLRF TRISD BCF STATUS,RP0 MOVLW B'10000000' MOVWF ADCON0 MOVLW B'10010000' MOVWF ADCON0 MOVLW B'10011000' MOVWF ADCON0 |
;(5)Bank 1 へ切替 ;(6)RA0〜5アナログ、結果右詰 ;(7)ADCON1レジスタの設定 ;(8)PortB 出力モードに設定 ; PortC 出力モードに設定 ; PortD 出力モードに設定 ;(9)Bank 0 へ戻す ; ;(10)Fosc/32,CH0 設定, A/D off ;(11)ADCON0レジスタの設定 ;(10)Fosc/32,CH2 設定, A/D off ;(11)ADCON0レジスタの設定 ;(10)Fosc/32,CH3 設定, A/D off ;(11)ADCON0レジスタの設定 |
;*********************************************************** ; メインプログラム ;*********************************************************** |
|
MAIN MOVLW 3 MOVWF PC_LOC ADSTART MOVF PC_LOC,W CALL SELECT_LED MOVWF PORTC MOVF PC_LOC,W CALL SELECT_AD MOVWF ADCON0 CALL TIME_ACQ BSF ADCON0,GO WAIT BTFSC ADCON0,GO GOTO WAIT MOVF ADRESH,W MOVWF PORTB BSF STATUS,RP0 MOVF ADRESL,W BCF STATUS,RP0 MOVWF PORTD CALL TIME1S DECFSZ PC_LOC,F GOTO ADSTART GOTO MAIN |
;(12)ロケーションカウンタの初期値 ; ロケーションカウンタの設定 ;(13)ロケーションカウンタをWregにロードする ;(14)CH 表示の判別サブルーチンへ ;(15)PortCへ CH 判別データを出力 ; ;(16)ロケーションカウンタをWregにロードする ;(17)CH 設定サブルーチンへ ;(18)ADCON0レジスタの設定 ; ;(19)20μs 一定時間待つ(アクィジション時間) ;(20)A/D スタート ;(21)A/D が完了すると GOが0になる ;(22)GO が 0 だったらループから抜ける ; GO が 1 だったら WAIT へループする ;(23)A/D データ上位(データは右詰) ;(24)PortBへ A/D 結果を出力 ;(25)Bank 1 へ切替 ;(26)A/D データ下位 ;(27)Bank 0 へ戻す ;(28)PortDへ A/D 結果を出力 ; (29)1秒間 表示 ; (30)ロケーションカウンタ−1 ; A/D 変換を繰り返す ; ロケーションカウンタ 2→1→0 |
;*********************************************************** ; CH 表示の判別サブルーチン ;*********************************************************** |
|
SELECT_LED ADDWF PCL,F NOP RETLW B'00001000' RETLW B'00000100' RETLW B'00000001' |
;(31)プログラムカウンタ+ロケーションカウンタ ;(32)ダミー行 ;(33)CH3 表示のデータを Wregにロード ;(34)CH2 表示のデータを Wregにロード ;(35)CH0 表示のデータを Wregにロード |
;*********************************************************** ;A/D CH設定のサブルーチン ;*********************************************************** |
|
SELECT_AD ADDWF PCL,F NOP RETLW B'10011001' RETLW B'10010001' RETLW B'10000001' |
;(36)プログラムカウンタ+ロケーションカウンタ ;(37)ダミー行 ;(38)Fosc/32,CH3 設定, A/D on を Wregにロード ;(39)Fosc/32,CH2 設定, A/D on を Wregにロード ;(40)Fosc/32,CH0 設定, A/D on を Wregにロード |
;*********************************************************** ;遅延サブルーチン ;*********************************************************** ;アクィジション時間(20μs)の遅延サブルーチン(20MHzクロック時) |
|
TIME_ACQ MOVLW 20H MOVWF COUNT NOP LOOP_ACQ DECFSZ COUNT,F GOTO LOOP_ACQ RETURN |
;(41)1サイクル 20H = 32 ;(42)1サイクル ;(43)1サイクル 微調整ダミー ;(44)1×(32-1)+2 = 33サイクル ;(45)2×(32-1) = 62サイクル ;(46)2サイクル ; 合計 100サイクル×0.2μs = 20μs |
;100μs遅延サブルーチン(20MHzクロック時) |
|
TIME100 MOVLW 0A5H MOVWF COUNT NOP NOP LOOP DECFSZ COUNT,F GOTO LOOP RETURN |
; 1サイクル A5H=165 ; 1サイクル ; 1サイクル 微調整ダミー ; 1サイクル 微調整ダミー ; 1×(165-1)+2 = 166サイクル ; 2×(165-1) = 328サイクル ; 2サイクル ; 合計 500サイクル×0.2μs = 100μs |
;10ms遅延サブルーチン(20MHzクロック時) | |
TIME10M MOVLW 63H MOVWF COUNT1 NOP NOP LOOP1 CALL TIME100 DECFSZ COUNT1,F GOTO LOOP1 RETURN |
; 1サイクル 63H=99 ; 1サイクル ; 1サイクル 微調整ダミー ; 1サイクル 微調整ダミー ; (2+500)×99=49698サイクル ; 1×(99-1)+2 = 100サイクル ; 2×(99-1) = 196サイクル ; 2サイクル ; 合計 50000サイクル×0.2μs = 10ms |
;1s遅延サブルーチン(20MHzクロック時) | |
TIME1S MOVLW 63H MOVWF COUNT2 MOVLW 62H MOVWF COUNT3 MOVLW 03H MOVWF COUNT4 NOP LOOP2 CALL TIME10M DECFSZ COUNT2,F GOTO LOOP2 LOOP3 CALL TIME100 DECFSZ COUNT3,F GOTO LOOP3 LOOP4 DECFSZ COUNT4,F GOTO LOOP4 RETURN END |
; 1サイクル 63H=99 ; 1サイクル ; 1サイクル 62H=98 ; 1サイクル ; 1サイクル 03H=3 ; 1サイクル ; 1サイクル 微調整ダミー ;(2+50000)×99=4950198サイクル ; 1×(99-1)+2 = 100サイクル ; 2×(99-1) = 196サイクル ;(2+500)×98=49196 ; 1×(98-1)+2 = 99サイクル ; 2×(98-1) = 194サイクル ; 1×(3-1)+2 = 4サイクル ; 2×(3-1) = 4サイクル ; 2サイクル ; 合計 5000000サイクル×0.2μs = 1s |
【プログラムの説明(3)】
このプログラムについて、順を追って解説を加えておきましょう。
(1)プロセッサの種別指定
定義の仕方は「PROCESSOR」か「LIST」命令を使って設定します。ここで指定するプロセッサ名称は、パッケージの種類を示すサフィックス(最後の英記号の部分)は不要です。
PROCESSOR PIC16F877
または
LIST P=PIC16F877
(2)標準ヘッダーファイルのインクルード
標準ヘッダーファイルとは、各プロセッサが持っているSFR(Special
Function Register)をラベル(記号)で使える様にするため、ラベルとハードウェアの場所とを定義しているファイルです。標準ヘッダーファイルは 「プロセッサ名.INC」というファイル名で統一されて、MPLABのディレクトリに格納されています。従って、これのインクルード方法は下記のようにして行います。
一度、参考までに標準ヘッダーファイルの内容をエディタ等で見ておくことをお勧めします。
INCLUDE P16F877.INC
または
#INCLUDE P16F877.INC
(3)変数定義とレジスタ割付
レジスタファイルアドレスを指定するときに、アドレス数値を直接指定することもできますが、数値だけでは間違いも多く、プログラム自身も分かりにくくなってしまいます。そこで、EQU命令などを使ってラベルを設定し変数を定義します。レジスタファイルアドレスは、7ビットあるので、00〜7Fまで最大128個のレジスタが指定できますが、実際に物理的に実装されて汎用的に使用できるレジスタ数はデバイスによって異なっていますので注意が必要です。
PIC16F877の汎用レジスタのアドレスは、20H〜7FH
となっていますので、20H以降のアドレスに割り付けます。
(4)プログラムの開始番地の指定
「ORG」はプログラムの開始番地を指定する擬似命令で、ORG以下の実際のプログラム命令が格納されるプログラムメモリ内の位置(アドレス)を指定します。
ORG 0 ;0番地から格納することを示します。
コンピュータは一般に電源投入時やリセットをすると必ず0番地からスタートするようになっているので、0番地には必ず命令があることが必要です。
(5)Bank 1 へ切替
PICには各種の動作モードを設定するための Special
Register と呼ばれるものが用意されています。PICを動作させるためには、まずこのSpecial
Registerの設定から始めます。そしてそれらは全て、Register
File と呼ぶメモリとして用意されています。その
Register Fileは Bank0, Bank1, Bank2, Bank3
とよばれるアドレス空間をもっているため、多少アクセスの仕方が面倒です。つまりRESET後の通常はBank0となっているので、Bank1側のレジスタにアクセスするときはBankの切替えをしてからとなります。またBank0とBank1に同じ物があるときにはどちらでも同じ様に使えます。
Bank1へ切り替える方法ですが、「STATUS」レジスタにある2ビットのRP0、RP1を変えてBankを指定します。デフォルトは、Bank0です。表1にBankとRP1,RP0ビットとの関係を示します。Bank1へ切り替えるためには、RP0ビットを「1」にします。(RP1はデフォルトで「0」なので変える必要はない。)
BSF STATUS,RP0
「STATUS」レジスタのRP0ビットを「1」にする。
Bank | RP1 | RP0 |
0 | 0 | 0 |
1 | 0 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
(6)RA0〜RA5のポートをアナログ、結果右詰
A/D変換器の入力ポートとして、(RA0/AN0),(RA2/AN2),(RA3/AN3)を使います。ここで、「A/D変換の制御法」の表3.A/D ポートの設定表にて、A/Dポートの設定を確認します。PCFGx=「0010」のとき、RA0〜RA5のポートがA/D変換入力ポートとなり、REポートはディジタル入出力ポートになることが分かります。A/D
結果フォーマットは右詰に設定します。
bit7: A/D 結果フォーマットセレクト:右詰=「1」
bit6: 機能なし(とりあえず「0」とでもしておく)
bit5: 機能なし(とりあえず「0」とでもしておく)
bit4: 機能なし(とりあえず「0」とでもしておく)
bit3: PCFG3=「0」
bit2: PCFG2=「0」
bit1: PCFG1=「1」
bit0: PCFG0=「0」
ということで、B’10000010’ (82H)をWregにロードする。
(7)ADCON1レジスタの設定
Wregの内容をADCON1レジスタに上書きする。
(8)PortB,C,Dを 出力モードに設定
TRISB,TRISC,およびTRISDレジスタは、CLRF(fレジスタをゼロクリアする命令)で出力設定となります。
CLRF TRISB
「TRISBレジスタをゼロクリアする。すなわち、PORTB全ポートを出力に設定する」
CLRF TRISC
「TRISCレジスタをゼロクリアする。すなわち、PORTC全ポートを出力に設定する」
CLRF TRISD
「TRISDレジスタをゼロクリアする。すなわち、PORTD全ポートを出力に設定する」
なお、PortAの設定ですが、デフォルトがA/D入力ポートになりますので省略できます。
(9)Bank 0 へ戻す
動作モードの設定後は、Bank0に戻しておきます。Bank1へ切り替えるためには、RP0ビットを「0」にします。(RP1はデフォルトで「0」なので変える必要はない。)
BCF STATUS,RP0
「STATUS」レジスタのRP0ビットを「0」にする。すなわち、Bank0に戻す。」
(10)Fosc/32,CH 設定,A/D off
「A/D変換の制御法」の表4.A/D変換用クロックの選択を参照してください。内部RC発振回路を使用するFrc指定の場合は、システムクロックには影響されず、2〜6μsの周波数になりますが、正確なクロック周波数ではなくなります。そこで、Fosc/2,Fosc/8,Fosc/32のどれかを選ぶことになります。システムクロックの周波数により、指定できる範囲が限られていますので注意が必要です。正しいA/D
変換のためには、必ずA/D 変換クロック(TAD)を、最小TAD
時間の1.6μs以上にする必要がありました。
20MHzのシステムクロックでは、Fosc/32を選択することになります。
また、「A/D変換の制御法」の表1.ADCON0レジスタの機能説明表を参照してください。
アナログチャネル指定ビットですが、
CHSx=「000」とすることで、CH0(RA0)の指定になります。
ということで、ADCON0→B’10000000’ (80H)
CHSx=「010」とすることで、CH2(RA2)の指定になります。
ということで、ADCON0→B’10010000’ (90H)
CHSx=「011」とすることで、CH3(RA3)の指定になります。
ということで、ADCON0→B’10011000’ (98H)
(11)ADCON0レジスタの設定
Wregの内容をADCON0レジスタに上書きする。
(12)ロケーションカウンタの初期値設定
ここで、ロケーションカウンタを設定したのは、「CH 表示の判別サブルーチン」や、「A/D
CH設定のサブルーチン」のところで、PCレジスタにこのロケーションカウンタの数字を加え、相当するロケーションへジャンプさせるためです。ジャンプ先には、それぞれCH
表示のデータや、A/D CH設定のデータを記載しておき、そのデータをRETLW命令を使ってWregに読み込んでリターンします。このロケーションカウンタは、「PC_LOC」という変数に入れておきます。
(13)ロケーションカウンタをWregにロードする
「PC_LOC」という変数に入っているロケーションカウンタ値をWregにロードします。
(14)CH 表示の判別サブルーチンへジャンプする
サブルーチンの内容の詳細は、「CH 表示の判別サブルーチン」の説明を見てください。
(15)PortCへ CH 判別データを出力
「CH 表示の判別サブルーチン」で、CH判別データがWregに格納されてきます。そのCH判別データをPortCへ出力し、データに対応するLEDが点灯します。
(16)ロケーションカウンタをWregにロードする
「PC_LOC」という変数に入っているロケーションカウンタ値をWregにロードします。
(17)CH 設定サブルーチンへジャンプする
サブルーチンの内容の詳細は、「CH 設定サブルーチン」の説明を見てください。
(18)ADCON0レジスタの設定
「CH 設定サブルーチン」で、設定データがWregに格納されてきます。
ここで、WregのデータをADCON0レジスタに移して設定します。
(19)20μs 一定時間待つ
PICでは、A/D変換をするために、まずアナログ信号を一旦内部のコンデンサに蓄えます。その後、参照となる一定の電圧を加算して比較しながら計測するという逐次変換方式であるため、A/D変換を正確に行うためには、蓄積するまでの時間(アクィジション時間)が必要です。
10ビットではアクィジション時間=20μsになります。
ここで、アクィジション時間(20μs)の遅延サブルーチンにジャンプします。
(20)A/D スタート
ADCON0レジスタのGOビットをセットすると、A/D変換が開始されます。
BSF ADCON0,GO
「ADCON0」レジスタのGOビットを「1」にする。すなわち、A/D変換を開始する。」
(21)A/D が完了すると GOビットが0になる
A/D変換を開始してから12TADの変換時間すなわち、12×1.6μs=19.2μs必要となります。A/Dが完了するとGOビットが「0」となりますので、時間で確認す
る必要はありません。
(22)GOビットが 0 だったらループから抜ける。
GO が 1 だったら WAIT へループする
A/D変換が完了するとGOビットが「0」となり、次の命令で分岐されます。
BTFSC ADCON0,GO
「ADCON0」レジスタのGOビットが「0」だったら次の命令をスキップし、ループから抜けます。
GOTO WAIT
ただし、A/D変換が終了しない間は、「ADCON0」レジスタのGOビットが「1」のままですので、WAITラベルへ戻ってループを繰り返します。
(23)A/D データ上位(データは右詰)
MOVF ADRESH,W
「ADRESH」レジスタの内容をWregに上書きする。
データは右詰ですので、ADRESHの<1:0>ビットに上位データが入り、他のビットは「0」が入ります。
(24)PortBへ A/D 結果を出力
Wregのデータは、ADRESHレジスタの値ですので、PortBの<1:0>ビットに上位データが出力され、他のビットは「0」となります。LEDは「1」となったビットで点灯します。
MOVWF PORTB
「PORTBへWregのデータを出力します。」
(25)Bank 1 へ切替
ADRESLレジスタは、Bank1にありますのでBankを切り替える必要があります。
(26)A/D データ下位
MOVF ADRESL,W
「ADRESL」レジスタの内容をWregに上書きする。
(注)もしBank1への切り替えを忘れて(Bank0のままで)、この命令を行った場合には、ADRESHレジスタの内容がWregに入ってしまいます。
(27)Bank 0 へ戻す
「ADRESL」レジスタの内容をWregに移したら、Bank0に戻しておきましょう。
(28)PortDへ A/D 結果を出力
Wregのデータは、ADRESLレジスタの値ですので、PortDに下位データが出力されます。LEDは「1」となったビットで点灯します。
MOVWF PORTD
「PORTDへWregのデータを出力します。」
(29)1秒遅延サブルーチンへ
ここでは、3入力にそれぞれ対応してLED点灯するA/D変換結果を、「目で見て」確認するため、1秒間待ちます。もし、LED表示の間隔がまだ短い(数秒にしたい)と感じたら、このCALL命令をいくつか記述してください。
(30)ロケーションカウンタ−1、 A/D 変換を繰り返す
「PC_LOC」という変数に入っているロケーションカウンタ値を−1します。
次の命令で「ADSTART」のラベルまで戻り、A/D変換動作を繰り返す。
ただし、ロケーションカウンタが、2→1→0となったときには、次の命令を飛ばして
GOTO MAINにて、「MAIN」のラベルまで戻り、A/D変換動作を繰り返します。
【CH 表示の判別サブルーチンの説明】
(31)プログラムカウンタ+ロケーションカウンタ
プログラムカウンタのPCLレジスタに、ロケーションカウンタ(Wregに入っている)を足すことで、次の命令をジャンプさせることができます。
たとえば、足されるロケーションカウンタ値が3であったならば、次に実行される命令は(32)ではなく(35)の行にジャンプします。
(32)ダミー行
(30)のところで、ロケーションカウンタ−1されて「0」となったときには、(12)で「3」に戻されます。したがって、このサブルーチン内では、ロケーションカウンタ値は「3」,「2」,「1」の3種類になります。ロケーションカウンタ値として「0」はありませんので、この行は実行されません。ダミーとして「NOP命令(何もしない)」を入れておきます。
(33)CH3 表示のデータを Wregにロードして戻る
3つのA/D変換入力ポートを使うため、どのポートのA/D変換結果なのか、RCポートのLEDを点灯させることでを確認しています。
ここではCH3のとき、RCポートの3ビット目を「1」とする設定にします。
RETLW B'00001000'
Wregに、3ビット目が「1」のリテラルデータを持って戻る。
(34)CH2 表示のデータを Wregにロードして戻る
ここではCH2のとき、RCポートの2ビット目を「1」とする設定にします。
RETLW B'00000100'
Wregに、2ビット目が「1」のリテラルデータを持って戻る。
(35)CH0 表示のデータを Wregにロードして戻る
ここではCH0のとき、RCポートの0ビット目を「1」とする設定にします。
RETLW B'00000001'
Wregに、0ビット目が「1」のリテラルデータを持って戻る。
【A/D CH設定のサブルーチンの説明】
(36)プログラムカウンタ+ロケーションカウンタ
(31)のところで解説した内容と同じです。プログラムカウンタのPCLレジスタに、ロケーションカウンタ(Wregに入っている)を足すことで、次の命令をジャンプさせることができます。
(37)ダミー行
(32)のところで解説した内容と同じです。このサブルーチン内では、ロケーションカウンタ値は「3」,「2」,「1」の3種類になります。ロケーションカウンタ値として「0」はありませんので、この行は実行されません。ダミーとして「NOP命令(何もしない)」を入れておきます。
(38)Fosc/32,CH3 設定, A/D on を Wregにロードして戻る
3つのA/D変換入力ポートを使うため、各ポートのADCON0レジスタの設定データをWregにロードします。
ここでは、CH3(RA3)のADCON0レジスタの設定データをロードします。
ということで、Wregに B’10011001’ (99H)のリテラルデータを持って戻る。
(39)Fosc/32,CH2 設定, A/D on を Wregにロードして戻る
ここでは、CH2(RA2)のADCON0レジスタの設定データをロードします。
ということで、Wregに B’10010001’ (91H)のリテラルデータを持って戻る。
(40)Fosc/32,CH0 設定, A/D on を Wregにロードして戻る
ここでは、CH0(RA0)のADCON0レジスタの設定データをロードします。
ということで、Wregに B’10000001’ (81H)のリテラルデータを持って戻る。
【20μs遅延サブルーチンの説明】
アクィジション時間(20μs)の遅延サブルーチン
(41)ループ回数(20H=32回)をWregにロードする。
(42)Wregの内容をfレジスタ(COUNT)に入れる
(43)サイクル数をちょうど100にするために、
1サイクル分のNOP命令(何もしないダミー)を入れた。
(44)fレジスタ(COUNT)の減算をし、結果が0なら次の命令をスキップする。
0以外である(32−1)回分は、1サイクル。
最後0になってスキップするとき2サイクル。
(45)(32−1)回分は、2サイクル
(46)サブルーチンから無条件復帰するとき、2サイクル
よって、計100サイクルになり、20MHzクロックでは、1サイクル0.2μsであることから、100サイクル×0.2μs=20μsになります。
その他の遅延サブルーチン
100μs,10ms,1s遅延サブルーチンの解説は、ここをクリックしてください。
A/D変換動作の確認
図3(a)に、A/D変換結果を表示するLED点灯の様子を示します。私のターゲットボードでは、PortBとPortDが隣り合って並んでいますので、10ビットの結果を右詰めに表示しています。したがって、
ADRESH<1:0>→PortB<1:0>
ADRESL<7:0>→PortD<7:0>
という配置に出力させます。
すなわち、10ビットのMSBから順に<RB1,RB0,RD7,RD6,・・・,RD0>となっています。
結果のビットですが、「1」のとき点灯し、「0」のとき消灯しています。
また、A/D変換入力ポートは3つありますので、RCポートのLEDを点灯させることで、どのポートでA/D変換が行われているかを確認できるようにしました。すなわち、CH0のときがRC0、CH2のときがRC2、CH3のときがRC3ポートのLEDを点灯するようにします。図3(b)に、各A/D変換入力ポートに対応するLED点灯の様子を示します。
![]() |
図3(a).A/D変換結果を表示する LED点灯の様子 |
![]() |
図3(b).各A/D変換入力ポートに 対応するLED点灯の様子 |
それでは、ターゲットボード上のLED点灯の結果から、ちゃんと動作しているかどうかチェックしていきましょう。表2に多入力のA/D変換結果をまとめてみました。
理論値の計算ですが、5V時の実測データ(4.97V)と、各電圧の実測データから次のように計算できます。(数字は10進表示、端数は四捨五入)
3V時は、1023×(3.001V/4.97V)=618
2V時は、1023×(2.003V/4.97V)=412
1V時は、1023×(1.004V/4.97V)=207
表2で、ターゲットボードの値と理論値を比べてみると、1LSB程度の誤差があるものの、A/D変換動作が確認されました。
A/D変換 入力CH |
RCポートの 点灯ビット |
入力電圧 ( )内は実測値 |
出力結果 | |||||
ターゲットボード | 理論値 | |||||||
2進 | 16進 | 10進 | 2進 | 16進 | 10進 | |||
0 | RC0 | 1V (1.004V) |
B’0011001110’ | H’0CE’ | D’206’ | B’0011001111’ | H’0CF’ | D’207’ |
2 | RC2 | 2V (2.003V) |
B’0110011100’ | H’19C’ | D’412’ | B’0110011100’ | H’19C’ | D’412’ |
3 | RC3 | 3V (3.001V) |
B’1001101001’ | H’269’ | D’617’ | B’1001101010’ | H’26A’ | D’618’ |
次へは、「PICのA/D変換の分解能の向上」について解説します
![]() |
![]() |
![]() |